Bundle Ubuntu Sans and Ubuntu Sans Mono (zennotes#890) - #43
Merged
Merged
Conversation
…nd iPad Settings → Typography could only offer fonts iOS ships, so the Ubuntu families the Android app bundles were missing on iPad and iPhone (ZenNotes/zennotes#890). The shell now ships the same files Android does (public/fonts, byte-identical: woff2 subsets for Latin, Cyrillic and Greek, upright and italic, Ubuntu Sans 100 to 800 and Ubuntu Sans Mono 400 to 700, with fonts.css and the Ubuntu Font Licence), links the stylesheet from index.html, and offers both names in the interface, text and monospace menus. The list moved to typography-fonts.ts so a test can hold every offered bundled face to a file that ships, and no file ships unused. About 0.55 MB more download. WebKit fetches a subset only once text is drawn in a bundled family, so cold start pays for the few KB of declarations. Monaco is not bundled: it is Apple's macOS font, licensed with macOS only, and not part of iOS. Menlo is in the list and SF Mono is the default. Checked on an iPad Pro 13-inch simulator (iOS 27.0): picking the families through the real menus set the editor, code and app chrome in them, and the bundled Latin, Cyrillic and Greek faces loaded.
) A high-severity advisory for braces (stack exhaustion on deeply nested patterns, no fixed release) failed the production npm audit gate on every pull request. It reached production through @excalidraw/excalidraw, which lists sass 1.51.0 as a dependency; that sass pulls in chokidar 3, which pulls in braces. Excalidraw never loads sass at runtime: nothing in its build output imports it. Excalidraw's sass is overridden to 1.103.1, the version the desktop repo already carries. It watches files with a chokidar that has no braces, so braces stays only under build tools. No existing package changes version.
renovate Bot
added a commit
to scottames/copr
that referenced
this pull request
Oct 6, 2026
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ZenNotes/zennotes](https://redirect.github.com/ZenNotes/zennotes) | minor | `2.60.0` → `2.62.0` | --- ### Release Notes <details> <summary>ZenNotes/zennotes (ZenNotes/zennotes)</summary> ### [`v2.62.0`](https://redirect.github.com/ZenNotes/zennotes/releases/tag/v2.62.0): ZenNotes v2.62.0 [Compare Source](https://redirect.github.com/ZenNotes/zennotes/compare/v2.61.0...v2.62.0) ZenNotes 2.62.0 brings ZenNotes to Finder: press Space on any Markdown file and Quick Look shows it the way ZenNotes renders it, with an Open in ZenNotes button. It also makes Cloud restores and backups behave the way they read, and tidies the rough edges ZenNotes Cloud's launch testing turned up. A restored note no longer leaves a copy behind, a refused backup names the limit it hit, Settings → Cloud opens on what needs you, and an embed whose file is not on this device says so instead of drawing an empty player. It also answers this week's reports: a Kanban board can order its cards by due date, link hints reach the links in the Edit view, ⌘W closes Settings and floating windows, Blinking cursor off holds in every window, and a dated wikilink like `[[2024.01.15]]` opens its note instead of the browser. Released from [`fb3d13f8`](https://redirect.github.com/ZenNotes/zennotes/commit/fb3d13f81c77d4fd3e69e5dcd24658ad0ad3b3d1) through [PR #​895](https://redirect.github.com/ZenNotes/zennotes/pull/895) on October 5, 2026. All installers are verified. #### Features - **Quick Look for Markdown files (macOS).** Select a `.md` file in Finder and press Space: Quick Look shows it rendered by ZenNotes' own Preview, in your theme and fonts, with callouts, tasks, tables, highlighted code, math, Mermaid diagrams and the images the note embeds. Open in ZenNotes opens it in the app (a note inside a vault you use opens there, any other file in its own window); once you click into the preview, Enter does the same, and with Vim mode on `o` opens it while `j` / `k`, Ctrl+D / Ctrl+U, `gg` and `G` move through the note. The preview is read-only and never goes online: website links open in your browser, and pictures hosted on the web are not loaded. It turns on after you open ZenNotes once, and System Settings → General → Login Items & Extensions → Quick Look turns it off. - **Order Kanban cards by due date.** The board's toolbar has Order next to Group by: Manual, as before, or Due date. By due date every column on every board, custom status boards included, sorts earliest first with cards without a date last, and a card moved to another column (a drag, `Shift+H` / `Shift+L`) lands in its date slot. Before, the first drag saved a hand-made order for the columns and that order won from then on, so a task whose date moved up stayed where it had been dragged. The dragged arrangement is kept while you order by date, and Manual brings it back exactly. The same switch is `s` on the board in Vim mode, `:order due | manual` on the Tasks ex line, the palette's "Kanban: Order Cards by Due Date", Settings → Tasks → Card order, and `kanban_card_sort` under `[view]` in config.toml ([#​889](https://redirect.github.com/ZenNotes/zennotes/issues/889)). - **Settings → Cloud shows a skipped automatic backup.** When the daily backup could not run, the Automatic daily backups row now says why: a plan limit is worded from its numbers ("The automatic backup on 10/5/2026 was skipped. This vault holds 54 MB, and backups on your plan hold up to 52 MB…"), anything else says the backup failed and will be tried again. Before, a skipped backup was silent. #### Fixes - **A restored note leaves no copy behind.** Restoring a Cloud backup that moved a note back (out of Trash, for example) wrote the note in its old place and left the copy where it had been; the next scan uploaded that copy as a new note to every device. The old copy now goes, but only when this device still holds exactly what it synced there; an edit made here since is kept and reported as a conflict. On the phones, a restore that only changed a note's capitalization could delete the only copy on storage that ignores case (Android's default); it now renames in place, and a phone stopped in the middle of that rename, or a save landing in the middle of it, no longer leaves a hidden copy behind or loses the save. - **A refused backup names the limit it hit.** "This backup would exceed your plan limits" now reads, for example, "This vault holds 54 MB, and backups on your plan hold up to 52 MB. Remove large files, or contact support to raise the limit.", and likewise for the file count and the number of backups kept. The restore prompt quotes the backup's label ("Restore “Weekly”?") and the result counts in the singular when it should. - **Settings → Cloud opens on what needs you.** The status bar's Review and Set up, and `Space r` or the palette after a Cloud vault was removed, open Settings on the Cloud page scrolled to This vault, with the keyboard on the first thing waiting (a removed-vault notice, a settings difference, a sync failure, files needing attention). Before, the page opened at its top with the keyboard in the settings search. - **The Cloud usage card stays current.** It read usage when Settings opened; it now reads it again a few seconds after a sync run moves files, and waits while the window is hidden. - **The restore result reads plainly.** "This vault is synced to cursor 18." is now "This vault now matches the backup." - **An embed whose file is not on this device says so.** A file too large for Cloud stays on the device that has it, while its note syncs everywhere; other devices drew `![[clip.mp4]]` as an empty player and images or PDFs as broken frames. Edit mode and Preview now show "clip.mp4 isn't on this device." in its place, and the embed turns into the player as soon as the file arrives. A file reached through a symlink is listed as an attachment and plays as before. - **Link hints label the links in the Edit view.** `Space h` labelled every control on screen and the links in Preview, but none of the links in the Edit view, which draws them as styled text. Hint mode now also labels the visible links of every open editor (bare URLs, `[[wikilinks]]` with an alias or a heading, Markdown links and images), down the note in reading order and never inside code, and following a label does what clicking the link does ([#​894](https://redirect.github.com/ZenNotes/zennotes/issues/894)). - **⌘W closes Settings and floating windows.** With Settings open, ⌘W closed the tab behind it (or the whole window once no tab was left), and in a floating note it did nothing. ⌘W now closes the frontmost window, the macOS rule, and Settings counts as one. Floating notes, the external-file window and Quick Capture close on it like their close button: a pending save is written first, and Quick Capture hides and keeps its draft. A rebind or unbind of Close active tab applies there too. While a dialog, palette or menu is open ⌘W does nothing, so it can never close the tab behind it ([#​893](https://redirect.github.com/ZenNotes/zennotes/issues/893)). - **Blinking cursor off holds in every window.** Floating notes, Quick Capture and the external-file window (and the reference pane and the template editor) kept blinking with Blinking cursor turned off. Every editor now follows the setting, and an open window follows a change made in Settings at once ([#​892](https://redirect.github.com/ZenNotes/zennotes/issues/892)). - **`[[2024.01.15]]` opens its note.** `gd`, `gD`, ⌘-click on a link's source, a link in a table cell, a database relation chip and a missing dated note clicked in Preview sent a wikilink with dots in its name to the browser as `https://2024.01.15`, even with the note right there, and `gy` offered to copy that address. A wikilink now reaches the browser only when it is written with a scheme (`[[https://…]]`); Markdown links keep reading `[site](example.com)` as a web address. - **A card's menu keeps what you type into it.** A card's right-click menu on the Kanban board filters as you type, and the manual suggests typing "prio"; the board's own single keys saw the letters first, so that `i` marked the card in progress (an `x` or a `c` would check it off or cancel it). Behind Settings the Tasks view's keys fired too: `1`, `2` and `3` switched the view and `a` opened the new-task prompt. Both now wait while a menu, a prompt or a dialog is open. - **Setting a value back in config.toml applies.** Change a setting in the app, then set it back by hand in `config.toml`, and the file is byte for byte what the app had written before; the app took that for a late echo of its own write and ignored it, so it stayed on the newer value while the file said otherwise. A put-back now applies like any other edit: at once, or about a second and a half later when the app has only just written the file. - **A right-click on a wikilink stays where you are.** In the Edit view a right-click on a rendered wikilink opened the linked note and then drew the menu over it, and on a link to a missing note it asked to create the note. Only the primary button follows a link now. #### For contributors - Quick Look lives in the new `apps/quicklook` workspace: the page (`src/`, app-core's Preview with a bridge shim, Typst and plot renderers left out, 11 MB), the sandboxed `ZenNotesQuickLook.appex` (Swift, serves the page and embedded files over `zenql://` behind a no-network CSP; WebKit still needs `network.client` to start), and `ZenNotesQuickLookOpener.xpc` inside it (unsandboxed, because Quick Look's sandbox lets a preview launch nothing). `apps/desktop/build/after-pack.js` builds and signs it per architecture with the app's identity and timestamp server, since electron-builder never signs `Contents/PlugIns`. `ZENNOTES_QUICKLOOK_SELFTEST=1` compiles a self-test for local validation (never in CI). `apps/quicklook/README.md` covers testing. The typography CSS variables moved from `App.tsx` to `lib/typography-variables.ts`. - Cloud sync: an upsert with a path change retires the previous path only when this device vouches for it (`retirePreviousPath`, inode-checked `sameFile`); the coordinator's matching-bytes shortcut no longer skips a move. The portable repository renames case-only through a temporary name, writes a record under `.zennotes/zennotes-cloud-sync/respellings` first, and skips the second step when a save took the name; `CloudSyncRepository.recoverInterruptedWork` (optional) settles leftover records at the start of every run and never fails it. - `cloudBackupLimitMessage` and `cloudBackupCreateError` in shared-domain word BACKUP_QUOTA_EXCEEDED details; `formatCloudBytes` moved to shared-domain (app-core re-exports it). `CloudBackupSchedule.last_failure` is declared in bridge-contract. - Browse (`packages/app-core/src/browse.ts`) now returns `files` rows for the phones' folder view, placed as the desktop sidebar places them; additive, unused by desktop and web. - The store records `assetFilesListed`, and `resolveLocalAsset()` reports `missing`; `indexImportedAssets` indexes an import before its embed is inserted. Desktop `listAssets` includes symlinked files; znserver needs [ZenNotes/znserver#11](https://redirect.github.com/ZenNotes/znserver/pull/11) in the release that pins this web artifact. - Phones: [ZenNotes/zennotesios#42](https://redirect.github.com/ZenNotes/zennotesios/pull/42) and [ZenNotes/zennotesandroid#95](https://redirect.github.com/ZenNotes/zennotesandroid/pull/95) carry the shell side (note dates follow renames, folder file rows, iOS folder vault list, Cloud UI tests); the file rows, media notice and Settings fixes reach the phones with a core built from this release. Shell-only fixes from the same issue round: [ZenNotes/zennotesandroid#96](https://redirect.github.com/ZenNotes/zennotesandroid/pull/96) and [ZenNotes/zennotesios#44](https://redirect.github.com/ZenNotes/zennotesios/pull/44) (Edit mode scrolling no longer snaps back to the caret, [#​891](https://redirect.github.com/ZenNotes/zennotes/issues/891)) and [ZenNotes/zennotesios#43](https://redirect.github.com/ZenNotes/zennotesios/pull/43) (Ubuntu Sans and Ubuntu Sans Mono bundled on iPhone and iPad, [#​890](https://redirect.github.com/ZenNotes/zennotes/issues/890)). - Links: `linkRangeAtCursor` reports the link's kind from the shared shape table (`linkRangesInLine` reads the same table), and `externalUrlForLink(target, kind)` decides what opens in the browser; `followLinkTarget` takes `kind`, and `extractLinkAtCursor`, which dropped it, is gone. Hint mode collects editor links in `lib/editor-link-hints.ts` and follows a wikilink through `openWikilink`. The rendered-wikilink mousedown handler ignores every button but the primary one. - Every editor builds its cursor layer through `lib/cm-cursor-blink.ts` (`cursorDrawSelection`, `storedCursorDrawSelection` for windows that read the prefs blob and follow its `storage` event); a test fails if another file calls `drawSelection()`. - Kanban ([#​889](https://redirect.github.com/ZenNotes/zennotes/issues/889)): `kanbanCardSort` (`'manual' | 'due'`) is a portable pref (`[view] kanban_card_sort`), global only and deliberately not a vault view override, which the Go server's vault.json mirror would have to learn. The board orders cards through `orderCards`; `compareCardsByDue` is the one comparator the column builders share (three copies before); `placeTaskInColumnOrder` writes nothing while ordered by date. `isOverlayOrDialogOpen` in `lib/overlay-open.ts` adds aria-modal dialogs and Settings to `isAppOverlayOpen`; the board and the Tasks view use it, the other list views still use the narrower check. - `apps/desktop/src/main/app-config.ts`: an earlier own-write text counts as a stale watcher read only while the module's own writes are landing (in flight, or within `OWN_WRITE_SETTLE_MS`, 1.5 s, of the last one), and a read skipped for that reason is re-checked once they settle. Remembering own-write texts with no time bound swallowed any hand edit that put an earlier version back. A read that outlives its watcher is dropped. - `lib/close-shortcut.ts`: `resolveCloseShortcut` decides what Mod+W does in the main window (close Settings, keep, Vim prefix, close tab, close window); `useCloseWindowShortcut` gives the floating, external-file and Quick Capture windows the same binding, rebinds included. Settings marks its panel `data-settings-dialog`. #### Verification How to test locally: 1. Build and launch with isolated stores: `npm run build --workspace @zennotes/desktop`, then `ZENNOTES_USER_DATA_PATH=$(mktemp -d) ZENNOTES_CONFIG_DIR=$(mktemp -d) npx electron apps/desktop/out/main/index.js`. 2. Missing media: in a note write `![[assets/nope.mp4]]`, `![[assets/nope.png]]` and `![[assets/nope.pdf]]`. Before: an empty player and broken frames. After: "nope.mp4 isn't on this device." (and so on) in Edit and Preview; copy a real `nope.png` into `assets/` and the card turns into the picture. 3. Restore (needs Cloud): move a note to Trash, sync, restore the backup from before. Before: the note in Inbox and a copy in Trash, uploaded to every device. After: only the note in Inbox. 4. Backup limits (needs Cloud on a small plan): Create backup on a vault over the limit. Before: "This backup would exceed your plan limits." After: the sentence names the size and the limit. 5. Settings → Cloud: with a kept-both conflict copy waiting, press Review on the status bar. Before: Settings at the top of the Cloud page. After: This vault in view, the file list focused. 6. Link hints ([#​894](https://redirect.github.com/ZenNotes/zennotes/issues/894)): in the Edit view open a note holding `https://example.net`, `[[ZenNotes]]`, `[GitHub](https://github.com)` and `` `https://code.test` ``, then press `Space h`. Before: labels on the toolbar and sidebar only. After: labels on the three links too, none on the code span; typing a label opens that link. 7. ⌘W ([#​893](https://redirect.github.com/ZenNotes/zennotes/issues/893)): with three tabs open press `⌘,` then `⌘W`. Before: Settings stays and a tab closes. After: Settings closes and the tabs stay. Run Open in Floating Window from the palette, then `⌘W` in it. Before: nothing. After: the window closes. In Quick Capture type a line and press `⌘W`: it hides, and the line is still there when it opens again. 8. Blinking cursor ([#​892](https://redirect.github.com/ZenNotes/zennotes/issues/892)): Settings → Editor, turn Blinking cursor off, then open a note in a floating window and open Quick Capture. Before: both blink. After: both hold still, and turning the setting back on makes both blink without reopening them. 9. Dotted wikilinks: make a note named `2024.01.15` and, in another note, write `[[2024.01.15]]`. With Vim on, put the caret in the link and press `gd` (or ⌘-click the link while its brackets show). Before: the browser opens <https://2024.01.15>. After: the note opens. Then right-click the rendered link. Before: the linked note opens under the menu. After: the menu opens where you are. 10. Quick Look: `cd apps/desktop && npx electron-builder --dir`, open the packed `dist/mac-arm64/ZenNotes.app` once (or `pluginkit -a dist/mac-arm64/ZenNotes.app/Contents/PlugIns/ZenNotesQuickLook.appex`), then select a note in Finder and press Space. Before: macOS showed the raw Markdown text. After: the note as ZenNotes renders it, in your theme, with Open in ZenNotes; pressing it opens the note in the app. (Opening a packed build also makes it the handler for `zennotes://`; see `apps/quicklook/README.md` for testing on a separate profile.) 11. Kanban card order ([#​889](https://redirect.github.com/ZenNotes/zennotes/issues/889)): in a scratch vault write `- [ ] Write spec @status:backlog due:2026-10-20`, `- [ ] Fix login @status:backlog due:2026-10-08`, `- [ ] Someday idea @status:backlog` and `- [ ] Ship v1 @status:backlog due:2026-10-12`, put `kanban_statuses = ["backlog", "doing", "review"]` under `[view]` in config.toml, and open Tasks → Kanban with Group by: Custom status. Drag Someday idea to the top of Backlog, then change Write spec's date to `2026-10-06`. Before: the column keeps the dragged order and Write spec stays at the bottom, with no way to sort by date. After: set Order to Due date (or press `s` with Vim on): Write spec, Fix login, Ship v1, Someday idea; `Shift+L` on a card lands it by date in the next column; Order: Manual brings back Someday idea on top. 12. Menu keys: with Vim on, right-click a card on the board and type `prio`. Before: the card turns `[/]` (in progress) and the menu filters on "pro". After: the menu narrows to the priority entries and the card is unchanged. Also press `⌘,` on the Tasks view and then `1`: before, the view behind Settings switched to List; after, nothing happens behind Settings. 13. config.toml put-back: launch as in step 1 but with a fixed config directory (`ZENNOTES_CONFIG_DIR=/tmp/zn-cfg`), open Tasks → Kanban, and set Order to Due date, then Manual, then Due date again. Wait two seconds, change `kanban_card_sort = "due"` back to `"manual"` in `/tmp/zn-cfg/config.toml` and save. Before: the board stays on Due date. After: it switches to Manual within half a second. #### Distribution channels - AUR 2.62.0-1: `beeb7d7`, mirrored in `372a44ba`; tarball SHA-256 `903baa6e...ca69cf4` matches GitHub's digest, the bundled CLI folder check passed, and the AUR package checks passed on `main` and the release branch. - Homebrew: tap `b28fc38`, mirrored in `8983e4ae`; the arm64 DMG was downloaded and its SHA-256 matches the cask and GitHub's digest, the x64 hash is GitHub's digest; `brew style` clean. - Nix: the first hash-generation run failed. The packaged app now carries `@parcel/watcher` and its prebuilt musl binary (sass 1.103.1, which this release's braces override gives Excalidraw, depends on it, and nothing loads it), and autoPatchelf could not satisfy `libc.musl-x86_64.so.1`. `93934229` drops the musl variants inside the Nix package; the rerun [37382323699](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37382323699) passed, `f16bbe0d` carries its values, and the main rebuild [37382901964](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37382901964) passed. `desktopHash` is the same tarball digest the AUR pins. [nixpkgs PR #​570652](https://redirect.github.com/NixOS/nixpkgs/pull/570652) carries 2.61.0 -> 2.62.0 as one commit on current master and awaits upstream review. Its source hash is the tag tarball's, computed with `nix store prefetch-file --unpack`; the same command reproduces master's current 2.61.0 hash. nixpkgs' derivation builds from source and has no autoPatchelf step. - `verify:channels -- 2.62.0` passed for Homebrew, AUR, Nix, and all seven website download routes. GitHub latest is v2.62.0. [Website PR #​62](https://redirect.github.com/ZenNotes/website/pull/62) merged at `ff57488f`. Its main tests and deploy passed (run [37384433044](https://redirect.github.com/ZenNotes/website/actions/runs/37384433044)), and zennotes.org/releases serves the 2.62.0 entry; the docs carry the Quick Look section and `:order`. - Self-hosted server: [znserver 2.62.0](https://redirect.github.com/ZenNotes/znserver/releases/tag/v2.62.0), released the same day, embeds this release's client code (`web-2.62.0-web.h53c3b6622d59ff2e`, published as a pre-release) and lists files reached through a symlink as assets ([znserver#11](https://redirect.github.com/ZenNotes/znserver/pull/11)); Docker `adibhanna/zennotes:2.62.0`, `2.62` and `latest` (linux/amd64 and linux/arm64, reporting v2.62.0). - Phones: iPhone 1.18.0 (34) and Android 1.1.32 (35) carry this release's app code as core `core-2.62.0-core.hcf81934394c63533`, published as a pre-release. Android 1.1.32 is live on Google Play and on GitHub with Play's universal APK; iPhone 1.18.0 is in App Review. #### Release validation - Fresh typechecks passed (no cache); 6,056 unit tests passed, 5 skipped (shared-domain 1,896, app-core 3,096, quicklook 15, desktop 1,049). - The signed local package (`npm run pack`) built and signed the Quick Look extension in afterPack, launched isolated with a CDP page in 1.5 seconds and reported 2.62.0; `codesign --verify --deep --strict` passed. Vim editor (12 checks), sidebar navigation (12) and editor improvements (19) smoke suites passed on the first run. - Release PR [#​895](https://redirect.github.com/ZenNotes/zennotes/issues/895): all 9 checks passed on `fb3d13f8`. - Release run [37379286092](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37379286092) passed on every platform on the first attempt, with 25 assets. - All four update manifests and their 13 referenced files passed size and downloaded SHA-512 verification. The app in the arm64 DMG passed notarization (`Notarized Developer ID`), staple and strict deep signature checks, reports 2.62.0, bundles `zn` v0.6.2, and carries `ZenNotesQuickLook.appex` with its opener service: the first CI build of the extension, signed by team WYY7PK57DM with the hardened runtime, a secure timestamp and the sandbox entitlements as designed. Quick Look itself was exercised end to end on a locally packed build during the cycle (Finder Space, Open in ZenNotes, Vim keys); the CI build's extension was checked for presence and signatures, not registered with Quick Look. - Issues [#​889](https://redirect.github.com/ZenNotes/zennotes/issues/889), [#​892](https://redirect.github.com/ZenNotes/zennotes/issues/892), [#​893](https://redirect.github.com/ZenNotes/zennotes/issues/893) and [#​894](https://redirect.github.com/ZenNotes/zennotes/issues/894) and the dotted-wikilink, menu-key and config.toml fixes were each driven in the built app over CDP on an isolated profile before they were committed. - Cloud: the restore fix was verified against production in the built app during the October 5 acceptance run (no duplicate, sequence unchanged). Billing was accepted separately in Stripe's sandbox, and publishing earlier the same day. ### [`v2.61.0`](https://redirect.github.com/ZenNotes/zennotes/releases/tag/v2.61.0): ZenNotes v2.61.0 [Compare Source](https://redirect.github.com/ZenNotes/zennotes/compare/v2.60.0...v2.61.0) ZenNotes 2.61.0 makes ZenNotes Cloud say what it is waiting on. A note paused by a sync conflict says so on the note, Cloud's limits name the file and the limit, and a deleted Cloud vault no longer stops syncing in silence. Videos and audio play in the editor, the backup browser reaches every file, and heading links follow in the reading view. Released from [`80c284b8`](https://redirect.github.com/ZenNotes/zennotes/commit/80c284b8a6c125109f74b58d51600a2a5300f40f) through [PR #​887](https://redirect.github.com/ZenNotes/zennotes/pull/887) on October 2, 2026. All installers are verified. #### Features - **A note paused by a sync conflict says so on the note.** When the same note changes on two devices, a one-row banner across its top reads "Sync is paused for this note. It changed on this device and on another device.", in Edit, Preview and split alike, with a Review button that opens the conflict queue on that note (with Vim on, `Space r` does the same and the banner names it). A notification with Review appears once for each new conflict, stays quiet while the queue is open, and comes back if a resolved conflict returns. Before, the only sign was "1 file needs review" in the status bar, which zen mode hides. - **Videos and audio play in the editor.** Attaching or dropping an image, PDF, audio or video file now embeds it (`![[path]]`) instead of writing a link, and Edit mode draws a standalone audio or video line as the same player the reading view uses, with Open and `</>` (edit the line) in its header. - **The backup browser reaches every file.** Settings → Cloud → Backups → Browse notes now reads "Showing 50 of N notes" with **Load more**, and its search asks Cloud, matching any part of a path across the whole backup. Before, it listed the first 50 files and searched only those, so a note that sorted later could not be restored on its own. - **Deleting a Cloud vault asks for its name.** The dialog reads "Delete “Name” for every device?", says what is lost and what stays on your devices, points to Unlink this device for stopping on one device only, and keeps Delete disabled until the vault's exact name is typed. #### Fixes - **Cloud names what stopped a sync.** The status bar and Settings say "1 file too large for Cloud", "Cloud storage full" or "Cloud item limit reached" instead of "Sync incomplete", the message names the file ("“clip.mov” is larger than the 10 MB Cloud file-size limit, so it stays on this device."), and the note itself shows "Not synced to Cloud: larger than the 10 MB file-size limit, so it stays on this device." under that file. A 10 GB plan now reads 10 GB rather than 9.3 GB. - **A deleted Cloud vault no longer stops syncing in silence.** When a Cloud vault is deleted on another device or on the website, the devices still linked to it used to unlink quietly and show the success color. Now the status bar says "Cloud vault deleted" (or "Cloud vault unavailable" when Cloud refuses it to this account), and Settings → Cloud → This vault explains what happened until you link or create a vault, or dismiss the notice; Review, `Space r` and the new **Review Cloud Vault** palette entry all open it, and the notice survives a restart. Settings also stops offering a vault that is gone. - **Settings → Cloud after signing in.** Signing in while the page was still loading reported "Cloud account changed while loading credentials."; the newest load now wins and a cancelled one retries. Failures of This vault's actions appear inside This vault instead of at the top of the page, and messages no longer start with an internal class name such as "CloudServiceRequestError:". - **Large files sync in bounded steps.** Cloud now hands over large revisions as references fetched in bounded pages, downloads go to a staging file checked for length and SHA-256 before they replace a note or attachment, an interrupted catch-up keeps its place, sync honors Cloud's retry delays across windows, and it stops cleanly on sign-out and quit ([#​884](https://redirect.github.com/ZenNotes/zennotes/pull/884)). - **Heading links follow in the reading view.** A Markdown `[text](#heading)` had nothing to scroll to because rendered headings carried no id; it now lands on the heading, as do `#Heading%20Text` and `#heading-slug`, and a click on a `[[#Heading]]` link no longer opens the hover card first. - **Folder pickers on touch screens open without the keyboard.** On a touch screen, Move to… for a note or a folder shows the whole folder list; tap the field to type a path. Prompts with nothing to tap still open with the keyboard. - **Cloud never syncs another device's bookkeeping.** A vault that is also open on a phone could carry the phone's `zennotes-cloud-sync` folder, which then synced back and forth on every run; sync now skips it. - The **Review Cloud Sync Conflicts** palette entry names `Space r` only with Vim on, since the leader does nothing without it. #### For contributors - New optional bridge method `listCloudBackupItemsPage(backupId, { page, search })` with the desktop IPC handler `cloud-backup-items:page` (the vault comes from main-process state; page and a 200-character search are validated there). Hosts without it keep the old single page with local filtering. ZenNotes Cloud's backup items endpoint accepts `search` ([ZenNotes/website#57](https://redirect.github.com/ZenNotes/website/pull/57)). - The status row carries `data-cloud-sync-phase` and `data-cloud-sync-review`, and Settings marks its dialog with `data-settings-target`, so the phone shells can style and route without matching Tailwind classes. - The phones already carry this release's app code: core `2.60.4` ([core-2.60.4-core.hae0e49f9e5397fc2](https://redirect.github.com/ZenNotes/zennotes/releases/tag/core-2.60.4-core.hae0e49f9e5397fc2)) is in iPhone 1.17.1 and Android 1.1.31, and the self-hosted web client `web-2.60.4-web.ha0258ecc7b3c0133` is in [znserver 2.60.1](https://redirect.github.com/ZenNotes/znserver/releases/tag/v2.60.1). No new boundary artifacts are built for 2.61.0: the code is the same. #### Verification How to test locally: 1. Build and launch with isolated stores: `npm run build --workspace @zennotes/desktop`, then `ZENNOTES_USER_DATA_PATH=$(mktemp -d) ZENNOTES_CONFIG_DIR=$(mktemp -d) npx electron apps/desktop/out/main/index.js`. 2. Media: drop a short `.mp4` into a note. Before: `[clip.mp4](…)`. After: `![[…/clip.mp4]]` and a player in Edit mode and in Preview. 3. Heading links: put `[jump](#section-three)` at the top of a note and `## Section Three` far below, open Preview and click the link. Before: nothing. After: the note scrolls to the heading. 4. Cloud (needs an account): link a vault on two devices, take one offline, edit the same line on both, reconnect. Before: only the status bar knew. After: the note shows the banner and a notification offers Review, which opens the queue on that note. 5. Cloud backups: Settings → Cloud → Backups → Create backup, wait for Ready, Browse notes on a vault with more than 50 files. Before: 50 rows. After: "Showing 50 of N notes", Load more, and search finds files on later pages. 6. Cloud delete: Settings → Cloud → Delete Cloud vault. After: the dialog names the vault and keeps Delete disabled until its exact name is typed. Cancel. #### Distribution channels - AUR 2.61.0-1: `96731c2`, mirrored in `c9e2427f`; tarball SHA-256 `c0d8d21a...aa69b36` matches GitHub's digest, the bundled CLI folder check passed, and the AUR package checks passed on `main` and the release branch. - Homebrew: tap `1c0b680`, mirrored in `9a74e705`; both DMGs were downloaded and their SHA-256 matches the cask and GitHub's digests; `brew style` clean. - Nix: `fcd44f09`; hash-generation run [37078241465](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37078241465) and the main rebuild [37078403704](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37078403704) passed. `desktopHash` is the same tarball digest the AUR pins. [nixpkgs PR #​569616](https://redirect.github.com/NixOS/nixpkgs/pull/569616) carries 2.60.0 -> 2.61.0 as one commit on current master and awaits upstream review. Its source hash is the tag tarball's, which nixpkgs fetches differently from this repo's package, computed with `nix store prefetch-file --unpack`; the same command reproduces master's current 2.60.0 hash. - `verify:channels -- 2.61.0` passed for Homebrew, AUR, Nix, and all seven website download routes. GitHub latest is v2.61.0. [Website PR #​59](https://redirect.github.com/ZenNotes/website/pull/59) merged at `7beab52`; its main tests and deploy passed (run [37081053002](https://redirect.github.com/ZenNotes/website/actions/runs/37081053002)), and zennotes.org/releases serves the 2.61.0 entry. - Self-hosted server: [znserver 2.60.1](https://redirect.github.com/ZenNotes/znserver/releases/tag/v2.60.1), released the same day, embeds the same client code (`web-2.60.4-web.ha0258ecc7b3c0133`); Docker `adibhanna/zennotes:2.60.1`, `2.60` and `latest`. No server release follows 2.61.0, because the code is identical. - Phones: iPhone 1.17.1 (33) and Android 1.1.31 (34) carry this release's app code as core 2.60.4 and are in store review. #### Release validation - Fresh typechecks passed (no cache); 5,831 unit tests passed, 5 skipped (shared-domain 1,861, app-core 2,945, desktop 1,025). - The signed local package (`npm run pack`) launched isolated with a CDP page in 1.4 seconds, reporting 2.61.0 and bundling CLI 0.6.2; `codesign --verify --deep --strict` passed. Vim editor (12 checks), sidebar navigation (12) and editor improvements (19) smoke suites passed. - Release PR [#​887](https://redirect.github.com/ZenNotes/zennotes/issues/887): all 9 checks passed on `80c284b8`. - Release run [37077212178](https://redirect.github.com/ZenNotes/zennotes/actions/runs/37077212178) passed on every platform on the first attempt, with 25 assets. - All four update manifests and their 13 referenced files passed size and downloaded SHA-512 verification. The app in the arm64 DMG passed notarization (`Notarized Developer ID`), staple and strict deep signature checks, reports 2.61.0, and its bundled `zn` reports v0.6.2. - Cloud: the changes were exercised against production during the October 2 device acceptance run on a real iPhone and this desktop app, and the backup browser was checked against production with a 91-file backup. Publishing, full-vault restore and billing were not part of this release's checks. </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - Every minute (`* * * * *`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/scottames/copr). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMjUuMSIsInVwZGF0ZWRJblZlciI6IjQ0LjEzNC4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the iOS side of ZenNotes/zennotes#890: Settings → Typography now offers Ubuntu Sans and Ubuntu Sans Mono on iPhone and iPad, as the Android app has since 1.1.3.
What ships.
public/fonts/is a byte-identical copy of the Android shell's files (diff -rclean): 24 woff2 subsets (Latin, Cyrillic, Greek; upright and italic; Ubuntu Sans 100 to 800, Ubuntu Sans Mono 400 to 700),fonts.csswith the@font-facerules, and the Ubuntu Font Licence (UFL.txt).index.htmllinks the stylesheet;listSystemFontsoffers both names in the interface, text and monospace menus. About 0.55 MB more download; WebKit fetches a subset only when text is drawn in that family.Tests. The list moved to
src/bridge/typography-fonts.ts;typography-fonts.test.ts(6 tests) checks both families are offered, each has upright and italic Latin faces, every face points at a woff2 that ships, no file ships unused, each file is real woff2, the licence ships, andindex.htmllinks the CSS.npm test186/186,npm run typecheckclean.Simulator (iPad Pro 13-inch, iOS 27.0). Picking Ubuntu Sans Mono for Monospace, then Ubuntu Sans for Text and Interface, through the real menus set the editor, code and app chrome in those fonts; a load probe showed the bundled Latin, Cyrillic and Greek faces loading.
Not bundled: Monaco. It is Apple's macOS font, licensed with macOS only and not part of iOS. Menlo is in the list and SF Mono is the default.
Found, not changed here: "New York" in the list does not render on iOS (WebKit cannot address it by family name, so it falls back), and the first launch after a simulator boot can stay blank on this Xcode 27 setup until relaunched; both predate this change.